#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMap>
#include <QMainWindow>

namespace Ui {
class MainWindow;
}

typedef struct _tagDiskUsage {
    bool operator<(const struct _tagDiskUsage& other) const {
        return mount < other.mount; // sort by mount
    }
    bool valid;
    QString dev;
    QString mount;
    qint64 total;
    qint64 avail;
    double per()
    {
        return (double)((total - avail) / (double)total);
    }
} DISKUSAGE;

typedef struct _tagCoreUsage {
    bool valid;
    QString dev;
    qint64 total;
    qint64 idle;
}COREUSAGE;

typedef struct _tagIOState {
    bool valid;
    QString dev;
    qint64 r;
    qint64 w;
}IOSTATE;

typedef struct _tagDevTemp {
    bool valid;
    QString dev;
    QString temp;
}DEVTEMP;

typedef struct _tagNVSMI {
    bool valid;
    QString ver;
    QString tmem;
    QString fmem;
    QString temp;
}NVSMI;

typedef struct _tagProcList {
    int valid;
    float cper;
    char user[32];
    char cmd[64];
    qlonglong cpu;
    qlonglong mem;
    qlonglong pcpu;
    qlonglong pmem;
}PROCLIST;

typedef struct _tagSetup {
    int iDiskUsageCheckInterval;
    int iCPUUsageCheckInterval;
    int iDiskIOStateCheckInterval;
    int iNetIOStateCheckInterval;
    int iGPUTempCheckInterval;
    int iDiskTempCheckInterval;
    int iCoreTempCheckInterval;
    int iProcListCheckInterval;

    bool bStayOnTop;
    bool bStayOnBottom;
    bool bDecorator;
    bool bTransparent;
    float fOpacity;
    QColor clShadowColor;

    bool bEnableDateTime;
    bool bEnableCPUGraph;
    bool bEnableCPUTemp;
    bool bEnableCPUFreq;
    bool bEnableDiskUsage;
    bool bEnableDiskIO;
    bool bEnableDiskTemp;
    bool bEnableNetIO;
    bool bEnableGPUState;
    bool bEnableProcList;

    bool bCPUDrawBack;
    bool bCPUDrawBorder;
    bool bCPUHTML;
    QString CPUFormat;
    int CPUHeight;
    QFont CPUFont;
    QColor CPUBackColor;
    QColor CPUBorderColor;
    QColor CPUGraphColor;
    QColor CPUTextColor;

    bool bGPUDrawBack;
    bool bGPUDrawBorder;
    bool bGPUHTML;
    QString GPUFormat;
    int GPUHeight;
    QFont GPUFont;
    QColor GPUBackColor;
    QColor GPUBorderColor;
    QColor GPUGraphColor;
    QColor GPUTextColor;

    bool bDiskUsageDrawBack;
    bool bDiskUsageDrawBorder;
    bool bDiskUsageHTML;
    QString DiskUsageFormat;
    int DiskUsageHeight;
    QFont DiskUsageFont;
    QColor DiskUsageBackColor;
    QColor DiskUsageBorderColor;
    QColor DiskUsageGraphColor;
    QColor DiskUsageTextColor;

    bool bDiskIODrawBack;
    bool bDiskIODrawBorder;
    bool bDiskIOHTML;
    QString DiskIOFormat;
    int DiskIOHeight;
    QFont DiskIOFont;
    QColor DiskIOBackColor;
    QColor DiskIOBorderColor;
    QColor DiskIOGraphColor;
    QColor DiskIOTextColor;

    bool bNetIODrawBack;
    bool bNetIODrawBorder;
    bool bNetIOHTML;
    QString NetIOFormat;
    int NetIOHeight;
    QFont NetIOFont;
    QColor NetIOBackColor;
    QColor NetIOBorderColor;
    QColor NetIOGraphColor;
    QColor NetIOTextColor;

    bool bAnalog;
    bool bDateTimeDrawBack;
    bool bDateTimeDrawBorder;
    bool bDateTimeHTML;
    QString DateTimeFormat;
    int DateTimeHeight;
    QFont DateTimeFont;
    QColor DateTimeBackColor;
    QColor DateTimeBorderColor;
    QColor DateTimeGraphColor;
    QColor DateTimeTextColor;

    bool bProcListDrawBack;
    bool bProcListDrawBorder;
    bool bProcListHTML;
    QString ProcListFormat;
    int ProcListCount;
    int ProcListHeight;
    QFont ProcListFont;
    QColor ProcListBackColor;
    QColor ProcListBorderColor;
    QColor ProcListGraphColor;
    QColor ProcListTextColor;
}SETUP;


const int MAX_CORE = 8;
const int MAX_DEVICE = 64;

class MainWindow : public QMainWindow
{
    Q_OBJECT
    
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    QString OpenStateFile(QString file);
    QString RunCommand(QString cmd);
    QString getFullSettingFileName(QString name);
    QColor StringToColor(QString str);
    QString ColorToString(QColor color,bool bAlpha = true);
    void setSticky();
    void skipTaskNPager();
    void bottomLayer();

protected:
    void paintEvent(QPaintEvent*);
    void mouseMoveEvent(QMouseEvent* event);
    void mousePressEvent(QMouseEvent* event);
    void mouseReleaseEvent(QMouseEvent* event);
    void contextMenuEvent(QContextMenuEvent *event);

private:
    Ui::MainWindow *ui;

    int MAX_DISPLAY;

    QAction *ActSetup;
    QAction *ActClose;
    QAction *ActReload;

    SETUP setup;
    QRect mWindowPos;
    QPoint mMousePosition;
    bool mMoving;

    QTimer *timer;
    PROCLIST ProcMap[32768];
//    QMap<int, PROCLIST> ProcMap;
    QStringList ProcList;
    NVSMI gpuTemp;
    QList<DEVTEMP> DevTemp;
    IOSTATE DiskIOStateMax[MAX_DEVICE];
    IOSTATE NetIOStateMax[MAX_DEVICE];
    DISKUSAGE DiskUsage[MAX_DEVICE];
    QList<IOSTATE> DiskIO[MAX_DEVICE];
    QList<IOSTATE> NetIO[MAX_DEVICE];
    QList<COREUSAGE> CoreUsage[MAX_CORE];

    int CoreDisplayPos;
    int DiskUsageCount;
    int CoreCount;
    int DiskIOCount;
    int NetIOCount;
    int ProcessCount;

    qint64 msDiskUsageCheck;
    qint64 msCPUUsageCheck;
    qint64 msDiskIOStateCheck;
    qint64 msNetIOStateCheck;
    qint64 msGPUTempCheck;
    qint64 msDiskTempCheck;
    qint64 msCoreTempCheck;
    qint64 msProcListCheck;

    QString getSizeString(qint64 size);
    qint64 getDispMaxIO(qint64 io);
    void getDiskIOMax();
    void getNetIOMax();
    QString NetCat(QString ip,int port);

    int dispCaption(QPainter *p,int top);
    int dispTime(QPainter *p,int top);
    int dispDiskUsage(QPainter *p,int top);
    int dispCPUUsage(QPainter *p,int top);
    int dispDiskIOState(QPainter *p,int top);
    int dispNetIOState(QPainter *p,int top);
    int dispGPUTemp(QPainter *p,int top);
    int dispProcessList(QPainter *p,int top);

    void parseDiskUsage(QString str);
    void parseCPUUsage(QString str);
    void parseDiskIOState(QString str);
    void parseNetIOState(QString str);
    void parseGPUTemp(QString str);
    void parseDiskTemp(QString str);
    void parseCoreTemp(QString str);
    void parseProcessList(QString str);

private slots:
    void timerTimeout();
    void closeApp();
    void showSetup();
    void loadSettings(void);
    void saveSettings(void);
};

#endif // MAINWINDOW_H
